/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Server;

import Common.EmailStatusType;
import Common.Message;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import persistence.DataManager;

/**
 * Class intended to be the server of the Simple Email System
 *
 * @author Wilson Rolando Crespo Omonte
 */
public class MailServer implements Serializable {

    List<UserMessages> userMessages;
    private String serverName;
    Long ID;

    public MailServer() {
        this.userMessages = new LinkedList<>();
        this.ID = new Date().getTime();
    }
    
    
    

    public MailServer(String user, String serverName) {
        this();
        try {
            UserMessages userMessages1 = new UserMessages(user);
            userMessages.add(userMessages1);
            this.serverName = serverName + ".xml";
            new DataManager<MailServer>(this.serverName).save(this);
            //new DataManager<List<UserMessages>>(this.serverName).save(userMessages);
            //new DataManager<UserMessages>(this.serverName).save(userMessages1);
        } catch (IOException | ClassNotFoundException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
            
           
        }
    }
    
    public MailServer(String serverName) {
        this();
        this.serverName = serverName + ".xml";
        try {
            new DataManager<MailServer>(this.serverName).save(this);
        } catch (ClassNotFoundException | IOException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }

    public int getMessagesWaiting(String name) {
        int result = 0;
        for (UserMessages userMessages1 : userMessages) {
            result += verifyMessageOwner(userMessages1, name);
        }
        return result;
    }
    
    private int verifyMessageOwner(UserMessages userMessages1, String name) {
        String user = userMessages1.getUser();
        if (user.equalsIgnoreCase(name)) {
            List<Message> messages = userMessages1.getMessages();
            return messages.size();
        }
        return 0;
    }

    public Message getNextMessage(String name) {
        Message result = null;
        int i = 0;
        while (result == null && i < userMessages.size()) {
            result = getMessageIfCorresponds(userMessages.get(i), name);
            i++;
        }
        return result;
    }
    
    private Message getMessageIfCorresponds(UserMessages userMessages1, String name) {
        String user = userMessages1.getUser();
        if (user.equalsIgnoreCase(name)) {
            List<Message> messages = userMessages1.getMessages();
            return removeMessage(messages);
        }
        return null;
    }
    
    private Message removeMessage(List<Message> messages1) {
        if (messages1.size() > 0) {
            return messages1.get(0);
        }
        return null;
    }

    public void post(Message message) {
        String user = message.toString();
        String receiverUser = getReceiverUser(user);
        UserMessages receiverUserMessages = getReceiverUserMessages(receiverUser);
        if (receiverUserMessages != null) {
            try {
                List<Message> messages = receiverUserMessages.getMessages();
                messages.add(message);
                new DataManager<UserMessages>(this.serverName).save(receiverUserMessages);
            } catch (    IOException | ClassNotFoundException ex) {
                Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    private String getReceiverUser(String user) {
        String[] pieces = user.split(",");
        String[] secondPieces = pieces[1].split(":");
        return secondPieces[1].trim();
    }
    private boolean sendMessageIfCorresponds(UserMessages userMessages1, String receiverUser, Message message) {
        String userName = userMessages1.getUser();
        if (userName.equalsIgnoreCase(receiverUser)) {
            try {
                List<Message> messages = userMessages1.getMessages();
                messages.add(message);
                new DataManager<UserMessages>(this.serverName).save(userMessages1);
                return true;
            } catch (    IOException | ClassNotFoundException ex) {
                Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return false;
    }

    /**
     * this method will add a new user to existing
     * {@link UserMessages usermessages} list
     *
     * @param user, the name of the user to be added
     * @author Wilson Rolando Crespo Omonte
     */
    public void addUser(String user) {
        try {
            if (userMessages == null) {
                userMessages = new LinkedList<>();
            }
            boolean found = findUser(user);
            if (!found) {
                UserMessages newUserMessages = new UserMessages(user);
                userMessages.add(newUserMessages);
                new DataManager<UserMessages>(this.serverName + ".xml").save(newUserMessages);
            }
        } catch (IOException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    private boolean userExists(String user, UserMessages userMessages1) {
        String userName = userMessages1.getUser();
        return userName.equalsIgnoreCase(user);
    }
    
    public boolean findUser(String user) {
        boolean result = false;
        int i = 0;
        while (i < userMessages.size() && !result) {
            result = userExists(user, userMessages.get(i));
            i++;
        }
        return result;
    }
    public List<String> getRegisteredUsers() {
        List<String> result = new ArrayList<>();
        for (UserMessages userMessages1 : userMessages) {
            result.add(userMessages1.getUser());
        }
        return result;
    }

    public void deleteMessage(Message message) {
        int i = 0;
        boolean deleted = false;
        while (i < userMessages.size() && !deleted) {
            deleted = deleteMessageInList(userMessages.get(i), message);
            i++;
        }
    }

    private boolean deleteMessageInList(UserMessages userMessages1, Message message) {
        int i = 0;
        boolean deleted = false;
        List<Message> messages = userMessages1.getMessages();
        int size = messages.size();
        while (i < size && !deleted) {
            deleted = deleteMessageIfConcerns(messages.get(i), message);
            i++;
        }
        return deleted;
    }
    private boolean deleteMessageIfConcerns(Message message, Message messageToDelete) {
        if (message.equals(messageToDelete)) {
            message.delete();
            return true;
        }
        return false;
    }
    
    public List<Message> getNewMessages(String user) {
        List<Message> result = new ArrayList<>();
        List<Message> userMessages = getUserMessages(user);
        result = getNewMessagesFromList(userMessages);
        return result;
    }
    private List<Message> getUserMessages(String user) {
        List<Message> result = new ArrayList<>();
        boolean found = false;
        int i = 0;
        int limit = userMessages.size();
        while (i < limit && !found) {
            found = isUserMessages(user, userMessages.get(i));
            i++;
        }
        i--;
        if (found && i < limit) {
            UserMessages userMessages1 = userMessages.get(i);
            return userMessages1.getMessages();
        }
        return result;
    }

    private boolean isUserMessages(String user, UserMessages userMessages1) {
        String localUser = userMessages1.getUser();
        return localUser.equalsIgnoreCase(user);
    }

    private List<Message> getNewMessagesFromList(List<Message> userMessages1) {
        List<Message> result = new ArrayList<>();
        for (Message message : userMessages1) {
            addIfConcerns(result, message);
        }
        return result;
    }

    private void addIfConcerns(List<Message> result, Message message) {
        if (message.retrieveEmailCurrentStatus() == EmailStatusType.NEW) {
            result.add(message);
        }
    }

    public List<UserMessages> getUserMessages() {
        return userMessages;
    }

    public void setUserMessages(List<UserMessages> userMessages) {
        this.userMessages = userMessages;
    }

    public String getServerName() {
        return serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    private UserMessages getReceiverUserMessages(String receiverUser) {
        UserMessages result= null;
        boolean found = false;
        int i = 0;
        int limit = userMessages.size();
        while (i < limit && !found) {
            result = isReceiverUserMessages(userMessages.get(i), receiverUser);
            i++;
        }
        return result;
    }

    private UserMessages isReceiverUserMessages(UserMessages userMessages1, String receiverUser) {
        UserMessages result = null;
        String localUser = userMessages1.getUser();
        if (localUser.equalsIgnoreCase(receiverUser)) {
            result = userMessages1;
        }
        return result;
    }

    public Long getID() {
        return ID;
    }

    public void setID(Long ID) {
        this.ID = ID;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 37 * hash + Objects.hashCode(this.serverName);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MailServer other = (MailServer) obj;
        if (!Objects.equals(this.serverName, other.serverName)) {
            return false;
        }
        return true;
    }
    
    
    
}
